#include "anonymous_ftp_login.h"
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <fstream>
#include <iostream>
#include "functions.h"

using namespace std;
/*
  usage of this script

*/
void usage()
{
  cout << "anonymous_ftp_login ip [port]" << endl;
  cout << "\tip targetip" << endl;
  cout << "\tport ftp server's port default is 21" << endl;
  return;
}


/*
  this function is used to try to MKD in ftp dir
  @sd int socket id
*/
int anony_write(int sd)
{
  char command[MAX_DATA_SIZE];
  int res;
  char recvbuf[MAX_DATA_SIZE];

  snprintf(command, 512, "MKD mydir\r\n");
  send(sd, command, strlen(command), 0);
#if DEBUG
  cout << command << endl;
#endif
  res = recvtime(sd, recvbuf, MAX_DATA_SIZE, 3, NULL);
  if (res > 0) {
#if DEBUG
    recvbuf[res] = '\0';
    cout << "MKD recv : " << recvbuf <<endl;
#endif
    if (recvbuf[0] == '2') {
      snprintf(command, 512 , "RMD mydir\r\n");
      send(sd, command, strlen(command), 0);
      res = recvtime(sd, recvbuf, MAX_DATA_SIZE, 3, NULL);
      if (res > 0){
	recvbuf[res] = '\0';
#if DEBUG
	cout << "RMD recv : " << recvbuf <<endl;
#endif
      } else {
#if DEBUG
	cout << "RMD ERROR" <<endl;
#endif
      }
      return 1;
    } else {
      return 0;
    }
  }
  return 0;
}



/*
  this function is used to login a ftp server by anonymous:anony@info.com
  @param in sd      socket handle
*/
int anony_login(int sd)
{
  char buf[MAX_DATA_SIZE];
  char username[MAX_DATA_SIZE];
  char password[MAX_DATA_SIZE];
  char command[MAX_DATA_SIZE];
  int res;
  char recvbuf[MAX_DATA_SIZE];
  ifstream ReadFile("pwd.txt");
  //while (!ReadFile.eof()) {
  while (ReadFile.getline(buf, MAX_DATA_SIZE)) {
    //ReadFile.getline(buf, MAX_DATA_SIZE);
#if DEBUG
    cout << buf << endl;
#endif
    for(int i = 0 ; i < MAX_DATA_SIZE; i++) {
      if (buf[i] == ':') {
	memcpy(username, buf, i);
	username[i] = '\0';
#if DEBUG
	cout << "DEBUG : strlen(username) = " << strlen(username) << endl;
#endif
	memcpy(password, buf+(i+1), sizeof(buf) - i - 1);
	password[sizeof(buf)-i-1] = '\0';
#if DEBUG
	cout << "DEBUG : strlen(password) = " << strlen(password) << endl;
#endif
	break;
      }
    }
    cout << "DEBUG : username = " << username << endl;
    cout << "DEBUG : password = " << password << endl;
#if DEBUG
    cout << "Start login" << endl;
#endif
    snprintf(command, 512, "USER %s\r\n", username);
    send(sd, command, strlen(command), 0);
#if DEBUG
    cout << "DEBUG : command : " << command << endl;
#endif
    res = recvtime(sd, recvbuf, MAX_DATA_SIZE, 12, NULL);
    if (res < 0) {
      cout << "ERROR : recv problem for username " << username << endl;
      return 1;
    } else if (!res) {
      cout << "ERROR : recv timeout for username " << username << endl;
      continue;
    } else {
      recvbuf[res] = '\0';
      if (recvbuf[0] == '5') {
#if DEBUG
	cout << "DEBUG : you ftp server refuse login for username " << username << endl;
	cout << recvbuf << endl;
#endif
	continue;
      } else {
#if DEBUG
	cout << "recv info from username " << username << " : " << recvbuf << endl;
#endif
      }
    }
    snprintf(command, 512, "PASS %s\r\n", password);
    send(sd, command, strlen(command), 0);
#if DEBUG
    cout << "DEBUG : command : " << command << endl;
#endif
    res = recvtime(sd, recvbuf, MAX_DATA_SIZE, 12, NULL);
    if (res < 0 ) {
      cout << "ERROR : recv problem from password " << password << endl;
      return 1;
    } else if (!res) {
      cout << "ERROR : recv timeout for password " << password << endl;
      continue;
    } else {
      recvbuf[res] = '\0';
      if (recvbuf[0] == '5') {
#if DEBUG
	cout << "DEBUG : you ftp server refuse login for password " << password << endl;
#endif
	cout << recvbuf << endl;
	continue;
      } else {
#if DEBUG
	cout << "recv info from password " << password << " : " << recvbuf << endl;
#endif
      }
    }
#if DEBUG
    cout << "End Login" << endl;
    cout << "Start MKD" << endl;
#endif
    if (anony_write(sd)) {
      cout << "anonymous could write in root dir " << endl;
    } else {
      cout << "anonymous could not write in root dir " <<endl;
    }
#if DEBUG
    cout << "End MKD" <<endl;
    cout << "Try Incoming " <<endl;
#endif
    snprintf(command, 512, "CWD incoming\r\n");
    send(sd, command, strlen(command), 0);
    res = recvtime(sd, recvbuf, MAX_DATA_SIZE, 3, NULL);
    if (res > 0){
      recvbuf[res] = '\0';
      if (recvbuf[0] == '2') {
	if (anony_write(sd)) {
	  cout << "anonymous could write in incoming dir " <<endl;
	} else {
	  cout << "anonymous could not write in incoming dir " <<endl;
	}
      } else {
	cout << "CWD incoming recv : " << recvbuf <<endl;
      }
    }
#if DEBUG
    cout << "END Try Incoming " <<endl;
    cout << "QUIT" <<endl;
#endif
    const char *tmp = string("QUIT\r\n").c_str();
#if DEBUG
    cout << "DEBUG : strlen(tmp) = " << strlen(tmp) << endl;
#endif
    send(sd, tmp, strlen(tmp), 0);
#if DEBUG
    while ((res = recvtime(sd, recvbuf, MAX_DATA_SIZE, 3, NULL)) > 0) {
      recvbuf[res] = '\0';
      cout << "live from you ftp server : " << recvbuf << endl;
    }
#endif
    break;
  }
  ReadFile.close();
  return 0;
}

/*

  this function is called in int main file
  @param argc       arguments for global function number of arguments
  @param argv       arguments for global function arguments

*/

int action(int argc, char **argv)
{
  int sockfd;
  struct sockaddr_in dest_addr = {};
  char buf[MAX_DATA_SIZE];
  int num_of_byte;
  int ports[1025];
  int port=0;
  unsigned long ul = 1;
  struct timeval tm;
  char command[256];
  string s;
  ports[0] = 1;
  ports[1] = 21;
  if (argc != 2) {
    printf("参数个数不对\n");
    usage();
    return -1;
  } else {
#if DEBUG
    printf("IP: %s\n", argv[1]);
#endif
  }
  ifstream iplist(argv[1]);
  while ((getline(iplist, s))) {
    cout << s << endl;
    port = 0;
    if (port == 0) {
      int i = 1;
      for (i=1; i<= ports[0]; i++) {
	port = ports[i];
#if DEBUG
	printf("DEBUG: %d\n", port);
#endif
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	dest_addr.sin_family = AF_INET;
	dest_addr.sin_port = htons(port);

	dest_addr.sin_addr.s_addr = inet_addr(s.c_str());
	bzero(&(dest_addr.sin_zero), 8);
	ioctl(sockfd, FIONBIO, &ul);
	fd_set set;
	if (connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) == -1) {
	  tm.tv_sec = 3;
	  tm.tv_usec = 0;
	  FD_ZERO(&set);
	  FD_SET(sockfd, &set);
	  if (!select(sockfd+1, NULL, &set, NULL, &tm)) {
	    printf("connect timeout\n");
	    return 0;
	  }
	}
	num_of_byte = recvtime(sockfd, buf, MAX_DATA_SIZE, 2, NULL);
	if (num_of_byte > 0) {
	  buf[num_of_byte] = '\0';
	  printf("received: %s\n", buf);
	  //      close(sockfd);
	  printf("TRUE\n");
	  //  return 1;
	} else{
	  close(sockfd);
	  return 0;
	}
	if (!anony_login(sockfd)) {
	  cout << "guess successfule" << endl;
	  cout << "=========================================================" << endl;
	}
	close(sockfd);
      }
    }
  }
  return 0;

}

